home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / telecomm / misc / linkz88.lha / LinkZ88 / Source / serial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-12  |  26.1 KB  |  1,422 lines

  1. /***********************************************
  2.  **************    serial.c   ******************
  3.  ***********************************************/
  4.  
  5. #define INTUI_V36_NAMES_ONLY
  6.  
  7. #include <exec/exec.h>
  8. #include <intuition/intuition.h>
  9. #include <devices/serial.h>
  10.  
  11. #include <clib/exec_protos.h>
  12. #include <clib/intuition_protos.h>
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17.  
  18. #include "windows.h"
  19.  
  20. #include "consts.h"
  21. #include "structs.h"
  22. #include "protos.h"
  23.  
  24. extern prj_p prj;
  25.  
  26. typedef enum {
  27.     RDSTATE_NORMAL,
  28.     RDSTATE_ESCCODE,
  29.     RDSTATE_ESC1,
  30.     RDSTATE_ESC2
  31. }rdstate_e;
  32.  
  33. /*
  34. Function : BOOL serial_data_put(WORD *data,BOOL literal)
  35. Purpose : Sends data to the Z88, taking handshaking into account. 'data'
  36.     is an array of WORDs, each WORD representing 1 character to be
  37.     sent. The array is terminated by a -1. If 'literal' is TRUE, 0x1B
  38.     is sent as an ESC B sequence. Returns TRUE on success,
  39.     FALSE othewise.
  40. */
  41.  
  42. BOOL serial_data_put(WORD *data,BOOL literal)
  43. {
  44.     struct IntuiMessage *msg,curr_msg;
  45.  
  46.     ULONG signal_main,signal_serial,signals_returned;
  47.  
  48.     WORD data_put[5];
  49.     WORD data_num,data_put_num;
  50.  
  51.     UBYTE data_byte,temp_byte;
  52.  
  53.     BOOL done;
  54.  
  55.     /* Build signals */
  56.  
  57.     signal_main = 1L << mainwin->UserPort->mp_SigBit;
  58.     signal_serial = 1L << prj->serial_msg_port->mp_SigBit;
  59.  
  60.     for (data_num = 0; data[data_num] != -1; data_num++) {
  61.         /* Get the data byte */
  62.  
  63.         data_byte = (UBYTE)data[data_num];
  64.  
  65.         /* Set up bytes to send */
  66.  
  67.         if ((data_byte >= 0x20) && (data_byte <= 0x7F)) {
  68.             data_put[0] = (WORD)data_byte;
  69.             data_put[1] = -1;
  70.         }
  71.         else if ((data_byte == 0x09) || (data_byte == 0x0A) ||
  72. (data_byte == 0x0D)) {
  73.             data_put[0] = (WORD)data_byte;
  74.             data_put[1] = -1;
  75.         }
  76.         else if ((data_byte == 0x1B) && (!literal)) {
  77.             data_put[0] = (WORD)data_byte;
  78.             data_put[1] = -1;
  79.         }
  80.         else if ((data_byte == 0x1B) && (literal)) {
  81.             data_put[0] = (WORD)0x1B;        /* ESC */
  82.             data_put[1] = (WORD)0x42;        /* 'B' */
  83.             data_put[2] = (WORD)0x31;        /* '1' */
  84.             data_put[3] = (WORD)0x42;        /* 'B' */
  85.             data_put[4] = -1;
  86.         }
  87.         else {
  88.             data_put[0] = 0x1B;
  89.             data_put[1] = (WORD)'B';
  90.  
  91.             temp_byte =  data_byte >> 4;
  92.             if (temp_byte <= 9)
  93.                 data_put[2] = (WORD)(temp_byte + '0');
  94.             else
  95.                 data_put[2] = (WORD)(temp_byte - 10 + 'A');
  96.  
  97.             data_byte &= 0x0F;
  98.             if (data_byte <= 9)
  99.                 data_put[3] = (WORD)(data_byte + '0');
  100.             else
  101.                 data_put[3] = (WORD)(data_byte - 10 + 'A');
  102.  
  103.             data_put[4] = -1;
  104.         }
  105.  
  106.         for (data_put_num = 0; data_put[data_put_num] != -1;
  107. data_put_num++) {
  108.             /* Get the data byte */
  109.  
  110.             data_byte = (UBYTE)data_put[data_put_num];
  111.  
  112.             /* Set up the send request */
  113.  
  114.             prj->serialio->IOSer.io_Length = 1;
  115.             prj->serialio->IOSer.io_Data = &data_byte;
  116.             prj->serialio->IOSer.io_Command = CMD_WRITE;
  117.  
  118.             DoIO((struct IORequest *)prj->serialio);
  119.  
  120.             /* Set up the request for the Z88 0 handshake byte */
  121.  
  122.             prj->serialio->IOSer.io_Length = 1;
  123.             prj->serialio->IOSer.io_Data = &data_byte;
  124.             prj->serialio->IOSer.io_Command = CMD_READ;
  125.  
  126.             SendIO((struct IORequest *)prj->serialio);
  127.  
  128.             /* Wait for reply */
  129.  
  130.             done = FALSE;
  131.  
  132.             while (!done) {
  133.                 signals_returned = Wait(signal_main |
  134. signal_serial);
  135.  
  136.                 /* Window message */
  137.  
  138.                 if (signals_returned & signal_main) {
  139.                     while (msg =
  140. (struct IntuiMessage *)GT_GetIMsg(mainwin->UserPort)) {
  141.                         CopyMem(msg,&curr_msg,
  142. sizeof(struct IntuiMessage));
  143.                         GT_ReplyIMsg(
  144. (struct IntuiMessage *)msg);
  145.                         if (curr_msg.Class ==
  146. IDCMP_CLOSEWINDOW)
  147.                             cleanup();
  148.                     }
  149.                 }
  150.  
  151.                 /* Serial message */
  152.  
  153.                 if (signals_returned & signal_serial) {
  154.                     /* Data should be a zero */
  155.  
  156.                     if (CheckIO((struct IORequest *)prj->serialio)) {
  157.                         if (data_byte != 0) {
  158.                             error(
  159. "Corrupt handshaking, quitting.|"
  160. "Didn't receive correct 0 handshaking\n"
  161. "byte from Z88. Confused.",ERROR_WARNING,__LINE__,__FILE__);
  162.                             return(TRUE);
  163.                         }
  164.  
  165.                         WaitIO((struct IORequest *)prj->serialio);
  166.  
  167.                         done = TRUE;
  168.                     }
  169.                 }
  170.             }
  171.         }
  172.     }
  173.  
  174.     /* If we get here, we transferred the data OK and the Z88 received */
  175.     /* it OK. */
  176.  
  177.     return (TRUE);
  178. }
  179.  
  180. /*
  181. Function : BOOL serial_data_get(UBYTE *data,LONG size)
  182. Purpose : Gets data from Z88 and places into 'data'. Receives 'size' bytes
  183.     and de-mangles encoding of bytes outside 0x20 and 0x7F. Returns
  184.     TRUE on success, FALSE otherwise.
  185. */
  186.  
  187. BOOL serial_data_get(UBYTE *data,LONG size)
  188. {
  189.     struct IntuiMessage *msg,curr_msg;
  190.  
  191.     ULONG signal_main,signal_serial,signals_returned;
  192.  
  193.     LONG data_num = 0;
  194.  
  195.     UBYTE data_byte;
  196.  
  197.     BOOL done;
  198.  
  199.     rdstate_e state = RDSTATE_NORMAL;
  200.  
  201.     /* Build signals */
  202.  
  203.     signal_main = 1L << mainwin->UserPort->mp_SigBit;
  204.     signal_serial = 1L << prj->serial_msg_port->mp_SigBit;
  205.  
  206.     while (data_num < size) {
  207.         /* Set up the request for the Z88 data */
  208.  
  209.         prj->serialio->IOSer.io_Length = 1;
  210.         prj->serialio->IOSer.io_Data = &data_byte;
  211.         prj->serialio->IOSer.io_Command = CMD_READ;
  212.  
  213.         SendIO((struct IORequest *)prj->serialio);
  214.  
  215.         /* Wait for reply */
  216.  
  217.         done = FALSE;
  218.  
  219.         while (!done) {
  220.             signals_returned = Wait(signal_main | signal_serial);
  221.  
  222.             /* Window message */
  223.  
  224.             if (signals_returned & signal_main) {
  225.                 while (msg = (struct IntuiMessage *)GT_GetIMsg(
  226. mainwin->UserPort)) {
  227.                     CopyMem(msg,&curr_msg,
  228. sizeof(struct IntuiMessage));
  229.                     GT_ReplyIMsg((struct IntuiMessage *)msg);
  230.  
  231.                     if (curr_msg.Class ==
  232. IDCMP_CLOSEWINDOW)
  233.                         cleanup();
  234.                 }
  235.             }
  236.  
  237.             /* Serial message */
  238.  
  239.             if (signals_returned & signal_serial) {
  240.                 if (CheckIO((struct IORequest *)prj->serialio)) {
  241.  
  242.                     done = TRUE;
  243.  
  244.                     WaitIO((struct IORequest *)prj->serialio);
  245.                 }
  246.             }
  247.         }
  248.  
  249.         /* Perform actions depending on state */
  250.  
  251.         switch (state) {
  252.             case RDSTATE_NORMAL:
  253.                 if (data_byte >= 0x20) {
  254.                     /* Write out data byte direct */
  255.  
  256.                     data[data_num++] = data_byte;
  257.                 }
  258.                 else if ((data_byte == 0x09) ||
  259. (data_byte == 0x0A) || (data_byte == 0x0D)) {
  260.                     /* Write out data byte direct */
  261.  
  262.                     data[data_num++] = data_byte;
  263.                 }
  264.                 else if (data_byte == 0x1B) {
  265.                     if (size == 1)
  266.                         data[data_num++] = 0x1B;
  267.                     else
  268.                         state = RDSTATE_ESCCODE;
  269.                 }
  270.                 else {
  271.                     error("Corrupt data.|"
  272. "A byte outside the allowed\n"
  273. "range was found in the data\n"
  274. "stream.",ERROR_WARNING,__LINE__,__FILE__);
  275.                     return(FALSE);
  276.                 }
  277.                 break;
  278.             case RDSTATE_ESCCODE:
  279.                 if (data_byte != 'B') {
  280.                     data[data_num++] = 0x1B;
  281.                     data[data_num++] = data_byte;
  282.  
  283.                     state = RDSTATE_NORMAL;
  284.                 }
  285.                 else
  286.                     state = RDSTATE_ESC1;
  287.  
  288.                 break;
  289.             case RDSTATE_ESC1:
  290.                 if ((data_byte >= '0') && (data_byte <= '9'))
  291.                     data[data_num] = data_byte - '0';
  292.                 else if ((data_byte >= 'A') &&
  293. (data_byte <= 'F'))
  294.                     data[data_num] = data_byte - 'A' + 10;
  295.                 else {
  296.                     error("Corrupt data.|"
  297. "An ESC B sequence data was outside\n"
  298. "the range 0-9,A-F.\n",ERROR_WARNING,__LINE__,__FILE__);
  299.                     return(FALSE);
  300.                 }
  301.  
  302.                 /* Shift data */
  303.  
  304.                 data[data_num] <<= 4;
  305.  
  306.                 state = RDSTATE_ESC2;
  307.  
  308.                 break;
  309.             case RDSTATE_ESC2:
  310.                 if ((data_byte >= '0') && (data_byte <= '9'))
  311.                     data_byte -= '0';
  312.                 else if ((data_byte >= 'A') &&
  313. (data_byte <= 'F'))
  314.                     data_byte = data_byte - 'A' + 10;
  315.                 else {
  316.                     error("Corrupt data.|"
  317. "An ESC B sequence data was outside\n"
  318. "the range 0-9,A-F.\n",ERROR_WARNING,__LINE__,__FILE__);
  319.                     return(FALSE);
  320.                 }
  321.  
  322.                 data[data_num++] |= data_byte;
  323.  
  324.                 state = RDSTATE_NORMAL;
  325.  
  326.                 break;
  327.             default:
  328.                 error("Unknown RDSTATE.",ERROR_INTERNAL,
  329. __LINE__,__FILE__);
  330.                 break;
  331.         }
  332.  
  333.         /* Send the handshaking byte back */
  334.  
  335.         data_byte = 0;
  336.  
  337.         prj->serialio->IOSer.io_Length = 1;
  338.         prj->serialio->IOSer.io_Data = &data_byte;
  339.         prj->serialio->IOSer.io_Command = CMD_WRITE;
  340.  
  341.         DoIO((struct IORequest *)prj->serialio);
  342.     }
  343.  
  344.     /* If we get here, all's OK */
  345.  
  346.     return (TRUE);
  347. }
  348.  
  349. /*
  350. Function : BOOL serial_data_get_single(WORD *data)
  351. Purpose : Gets a single byte of (decoded) data. Sets 'data' to -1 if
  352.     ESC Z is found in stream. Returns TRUE on success, FALSE otherwise.
  353. */
  354.  
  355. BOOL serial_data_get_single(WORD *data)
  356. {
  357.     UBYTE data_bytes[2];
  358.     UBYTE data_byte;
  359.  
  360.     /* Get a byte of data */
  361.  
  362.     if (!serial_data_get(&data_byte,1))
  363.         return (FALSE);
  364.  
  365.     /* If normal value */
  366.  
  367.     if (data_byte >= 0x20) {
  368.         *data = (WORD)data_byte;
  369.  
  370.         return (TRUE);
  371.     }
  372.  
  373.     /* If special value */
  374.  
  375.     if ((data_byte == 0x09) || (data_byte == 0x0A) || (data_byte == 0x0D)) {
  376.         *data =(WORD)data_byte;
  377.  
  378.         return (TRUE);
  379.     }
  380.  
  381.     /* If not ESC, error */
  382.  
  383.     if (data_byte != 0x1B)
  384.         return (FALSE);
  385.  
  386.     /* Get the next byte to see which ESC code */
  387.  
  388.     if (!serial_data_get(&data_byte,1))
  389.         return (FALSE);
  390.  
  391.     /* If ESC Z */
  392.  
  393.     if (data_byte == 'Z') {
  394.         *data = -1;
  395.  
  396.         return (TRUE);
  397.     }
  398.  
  399.     /* If not ESC B, error */
  400.  
  401.     if (data_byte != 'B')
  402.         return (FALSE);
  403.  
  404.     /* Get next 2 bytes to work out real value */
  405.  
  406.     if (!serial_data_get(data_bytes,2))
  407.         return (FALSE);
  408.  
  409.     data_byte = data_bytes[0];
  410.  
  411.     if ((data_byte >= '0') && (data_byte <= '9'))
  412.         *data = (WORD)(data_byte - '0');
  413.     else if ((data_byte >= 'A') && (data_byte <= 'F'))
  414.         *data = (WORD)(data_byte - 'A' + 10);
  415.     else
  416.         return(FALSE);
  417.  
  418.     /* Shift data */
  419.  
  420.     *data <<= 4;
  421.  
  422.     data_byte = data_bytes[1];
  423.  
  424.     if ((data_byte >= '0') && (data_byte <= '9'))
  425.         data_byte -= '0';
  426.     else if ((data_byte >= 'A') && (data_byte <= 'F'))
  427.         data_byte = data_byte - 'A' + 10;
  428.     else 
  429.         return(FALSE);
  430.  
  431.     *data |= (WORD)data_byte;
  432.  
  433.     /* Return OK */
  434.  
  435.     return (TRUE);
  436. }
  437.  
  438.  
  439.  
  440. /*
  441. Function : BOOL serial_sync()
  442. Purpose : Sends the synchronising message. This is slightly
  443.     different that all the other transfer in that return 0 bytes
  444.     aren't returned. Returns TRUE on success, FALSE otherwise.
  445. */
  446.  
  447. BOOL serial_sync()
  448. {
  449.     struct IntuiMessage *msg,curr_msg;
  450.  
  451.     ULONG signal_main,signal_serial,signals_returned;
  452.  
  453.     UBYTE amisyncdata[] = {5,5,5,5,5,6};
  454.     UBYTE z88syncdata;
  455.  
  456.     BOOL correctdata;
  457.     BOOL done = FALSE;
  458.  
  459.     /* Set up the Amiga sync request */
  460.  
  461.     prj->serialio->IOSer.io_Length = 6;
  462.     prj->serialio->IOSer.io_Data = amisyncdata;
  463.     prj->serialio->IOSer.io_Command = CMD_WRITE;
  464.  
  465.     DoIO((struct IORequest *)prj->serialio);
  466.  
  467.     /* Set up the request for the Z88 sync data */
  468.  
  469.     prj->serialio->IOSer.io_Length = 1;
  470.     prj->serialio->IOSer.io_Data = &z88syncdata;
  471.     prj->serialio->IOSer.io_Command = CMD_READ;
  472.  
  473.     SendIO((struct IORequest *)prj->serialio);
  474.  
  475.     /* Build signals */
  476.  
  477.     signal_main = 1L << mainwin->UserPort->mp_SigBit;
  478.     signal_serial = 1L << prj->serial_msg_port->mp_SigBit;
  479.  
  480.     /* Wait for request or closewindow */
  481.  
  482.     while (!done) {
  483.         signals_returned = Wait(signal_main | signal_serial);
  484.  
  485.         /* Window message */
  486.  
  487.         if (signals_returned & signal_main) {
  488.             while (msg = (struct IntuiMessage *)GT_GetIMsg(
  489. mainwin->UserPort)) {
  490.                 CopyMem(msg,&curr_msg,
  491. sizeof(struct IntuiMessage));
  492.                 GT_ReplyIMsg((struct IntuiMessage *)msg);
  493.  
  494.                 if (curr_msg.Class ==
  495. IDCMP_CLOSEWINDOW)
  496.                     cleanup();
  497.             }
  498.         }
  499.  
  500.         /* Serial message */
  501.  
  502.         if (signals_returned & signal_serial) {
  503.             /* Even if it's returned, might not be the correct */
  504.             /* data. Just wait for the 6 */
  505.  
  506.             correctdata = FALSE;
  507.  
  508.             if (CheckIO((struct IORequest *)prj->serialio)) {
  509.                 if (z88syncdata == 6)
  510.                     correctdata = TRUE;
  511.  
  512.                 WaitIO((struct IORequest *)prj->serialio);
  513.             }
  514.  
  515.             if (correctdata)
  516.                 done = TRUE;
  517.             else {
  518.                 /* Build another request to listen for the */
  519.                 /* Z88 sync request. */
  520.  
  521.                 prj->serialio->IOSer.io_Length = 1;
  522.                 prj->serialio->IOSer.io_Data = &z88syncdata;
  523.                 prj->serialio->IOSer.io_Command = CMD_READ;
  524.  
  525.                 SendIO((struct IORequest *)prj->serialio);
  526.             }
  527.         }
  528.     }
  529.  
  530.     /* If we get here, return OK */
  531.  
  532.     return (TRUE);
  533. }
  534.  
  535. /*
  536. Function : BOOL serial_hello()
  537. Purpose : Sends the "Hello" transfer. Returns TRUE on success, FALSE
  538.     otherwise.
  539. */
  540.  
  541. BOOL serial_hello()
  542. {
  543.     WORD tags_hello[] = {
  544.         0x001B,        /* ESC */
  545.         0x0041,        /* 'A' */
  546.         -1};
  547.  
  548.     UBYTE tags_get[2];
  549.  
  550.     /* Synchronise the serial */
  551.  
  552.     win_status_set("Synchronising...");
  553.  
  554.     if (!serial_sync()) {
  555.         win_status_clear();
  556.  
  557.         return(FALSE);
  558.     }
  559.  
  560.     /* Send the message */
  561.  
  562.     win_status_set("Sending data...");
  563.  
  564.     if (!serial_data_put(tags_hello,FALSE)) {
  565.         win_status_clear();
  566.  
  567.         return (FALSE);
  568.     }
  569.  
  570.     /* Get reply */
  571.  
  572.     win_status_set("Receiving data...");
  573.  
  574.     if (!serial_data_get(tags_get,2)) {
  575.         win_status_clear();
  576.  
  577.         return (FALSE);
  578.     }
  579.  
  580.     /* Test return values */
  581.  
  582.     if ((tags_get[0] != 0x1B) || (tags_get[1] != 'Y')) {
  583.         error("Unknown Z88 reply.|"
  584. "The Z88 has not replied as expected\n"
  585. "from the \"Hello\" greeting.",ERROR_WARNING,__LINE__,__FILE__);
  586.  
  587.         win_status_clear();
  588.  
  589.         return (FALSE);
  590.     }
  591.  
  592.     /* Clear status window */
  593.  
  594.     win_status_clear();
  595.  
  596.     /* If we get here, all's OK */
  597.  
  598.     return (TRUE);
  599. }
  600.  
  601. /*
  602. Function : BOOL serial_devices()
  603. Purpose : Returns devices available on the Z88. Returns TRUE on success,
  604.     FALSE otherwise.
  605. */
  606.  
  607. BOOL serial_devices()
  608. {
  609.     WORD tags_devices[] = {
  610.         0x001B,        /* ESC */
  611.         0x0048,        /* 'H' */
  612.         -1};
  613.  
  614.     WORD count;
  615.  
  616.     UBYTE tags_get[2];
  617.     UBYTE data_byte;
  618.  
  619.     BOOL done = FALSE;
  620.  
  621.     struct listviewdata lvdata;
  622.  
  623.     rdstate_e state = RDSTATE_NORMAL;
  624.  
  625.     /* Synchronise the serial */
  626.  
  627.     win_status_set("Synchronising...");
  628.  
  629.     if (!serial_sync()) {
  630.         win_status_clear();
  631.  
  632.         return(FALSE);
  633.     }
  634.  
  635.     /* Send the message */
  636.  
  637.     win_status_set("Sending data...");
  638.  
  639.     if (!serial_data_put(tags_devices,FALSE)) {
  640.         win_status_clear();
  641.  
  642.         return (FALSE);
  643.     }
  644.  
  645.     /* Get reply */
  646.  
  647.     win_status_set("Receiving data...");
  648.  
  649.     /* Get tags, should be ESC N or ESC Z */
  650.  
  651.     if (!serial_data_get(tags_get,2)) {
  652.         error("Unable to get reply from Z88.",ERROR_WARNING,
  653. __LINE__,__FILE__);
  654.  
  655.         win_status_clear();
  656.  
  657.         return(FALSE);
  658.     }
  659.  
  660.     if (tags_get[0] != 0x1B) {
  661.         error("Unknown Z88 reply.|"
  662. "Expecting ESC N or ESC Z in reply\n"
  663. "to devices request.",ERROR_WARNING,__LINE__,__FILE__);
  664.  
  665.         win_status_clear();
  666.  
  667.         return(FALSE);
  668.     }
  669.  
  670.     if ((tags_get[1] != 'N') && (tags_get[1] != 'Z')) {
  671.         error("Unknown Z88 reply.|"
  672. "Expecting ESC N or ESC Z in reply\n"
  673. "to devices request.",ERROR_WARNING,__LINE__,__FILE__);
  674.  
  675.         win_status_clear();
  676.  
  677.         return(FALSE);
  678.     }
  679.  
  680.     /* If it's the end, no devices were returned */
  681.  
  682.     if (tags_get[1] == 'Z') {
  683.         win_status_clear();
  684.  
  685.         return (TRUE);
  686.     }
  687.  
  688.     /* Keep on reading device names */
  689.  
  690.     count = 0;
  691.  
  692.     while (!done) {
  693.         switch(state) {
  694.             case RDSTATE_NORMAL:
  695.                 /* Get the next byte */
  696.  
  697.                 if (!serial_data_get(&data_byte,1)) {
  698.                     error("Unable to read devices data.",
  699. ERROR_WARNING,__LINE__,__FILE__);
  700.  
  701.                     return (FALSE);
  702.                 }
  703.  
  704.                 /* If it's a normal character */
  705.  
  706.                 if (data_byte != 0x1B)
  707.                     lvdata.fname[count++] = data_byte;
  708.                 else
  709.                     state = RDSTATE_ESCCODE;
  710.  
  711.                 break;
  712.             case RDSTATE_ESCCODE:
  713.                 /* Get the ESC code */
  714.  
  715.                 if (!serial_data_get(&data_byte,1)) {
  716.                     error("Unable to read devices data.",
  717. ERROR_WARNING,__LINE__,__FILE__);
  718.  
  719.                     return (FALSE);
  720.                 }
  721.  
  722.                 /* If end of devices */
  723.  
  724.                 if (data_byte == 'Z') {
  725.                     lvdata.fname[count] ='\0';
  726.  
  727.                     win_listview_add(&lvdata,ZFILETYPE_DEV);
  728.  
  729.                     done = TRUE;
  730.                 }
  731.                 else if (data_byte == 'N') {
  732.                     lvdata.fname[count] ='\0';
  733.  
  734.                     win_listview_add(&lvdata,ZFILETYPE_DEV);
  735.  
  736.                     count = 0;
  737.                 }
  738.                 else {
  739.                     error("Unknown devices data.|"
  740. "ESC code received was not either\n"
  741. "N or Z.",ERROR_WARNING,__LINE__,__FILE__);
  742.  
  743.                     return (FALSE);
  744.                 }
  745.  
  746.                 state = RDSTATE_NORMAL;
  747.  
  748.                 break;
  749.             default:
  750.                 error("Unknown RDSTATE.",ERROR_INTERNAL,
  751. __LINE__,__FILE__);
  752.                 break;
  753.         }
  754.     }
  755.  
  756.     /* Clear the status */
  757.  
  758.     win_status_clear();
  759.  
  760.     /* Return OK */
  761.  
  762.     return (TRUE);
  763. }
  764.  
  765. /*
  766. Function : BOOL serial_directories()
  767. Purpose : Returns directories available on prj->zpath device on the Z88.
  768.     Returns TRUE on success, FALSE otherwise.
  769. */
  770.  
  771. BOOL serial_directories()
  772. {
  773.     WORD tags_directories[STRLEN_ZPATH];
  774.  
  775.     WORD tag_num = 0;
  776.     WORD count;
  777.  
  778.     UBYTE tags_get[2];
  779.     UBYTE data_byte;
  780.  
  781.     BOOL done = FALSE;
  782.  
  783.     struct listviewdata lvdata;
  784.  
  785.     rdstate_e state = RDSTATE_NORMAL;
  786.  
  787.     /* Synchronise the serial */
  788.  
  789.     win_status_set("Synchronising...");
  790.  
  791.     if (!serial_sync()) {
  792.         win_status_clear();
  793.  
  794.         return(FALSE);
  795.     }
  796.  
  797.     /* Set up request */
  798.  
  799.     tags_directories[tag_num++] = 0x001B;        /* ESC */
  800.     tags_directories[tag_num++] = 0x0044;        /* 'D' */
  801.  
  802.     for (count = 0; prj->zpath[count] != '\0'; count++)
  803.         tags_directories[tag_num++] = (WORD)prj->zpath[count];
  804.  
  805.     tags_directories[tag_num++] = 0x001B;        /* ESC */
  806.     tags_directories[tag_num++] = 0x005A;        /* 'Z' */
  807.     tags_directories[tag_num] = -1;
  808.  
  809.     /* Send the message */
  810.  
  811.     win_status_set("Sending data...");
  812.  
  813.     if (!serial_data_put(tags_directories,FALSE)) {
  814.         win_status_clear();
  815.  
  816.         return (FALSE);
  817.     }
  818.     /* Get reply */
  819.  
  820.     win_status_set("Receiving data...");
  821.  
  822.     /* Get tags, should be ESC N or ESC Z */
  823.  
  824.     if (!serial_data_get(tags_get,2)) {
  825.         error("Unable to get reply from Z88.",ERROR_WARNING,
  826. __LINE__,__FILE__);
  827.  
  828.         win_status_clear();
  829.  
  830.         return(FALSE);
  831.     }
  832.  
  833.     if (tags_get[0] != 0x1B) {
  834.         error("Unknown Z88 reply.|"
  835. "Expecting ESC N or ESC Z in reply\n"
  836. "to devices request.",ERROR_WARNING,__LINE__,__FILE__);
  837.  
  838.         win_status_clear();
  839.  
  840.         return(FALSE);
  841.     }
  842.  
  843.     if ((tags_get[1] != 'N') && (tags_get[1] != 'Z')) {
  844.         error("Unknown Z88 reply.|"
  845. "Expecting ESC N or ESC Z in reply\n"
  846. "to devices request.",ERROR_WARNING,__LINE__,__FILE__);
  847.  
  848.         win_status_clear();
  849.  
  850.         return(FALSE);
  851.     }
  852.  
  853.     /* If it's the end, no devices were returned */
  854.  
  855.     if (tags_get[1] == 'Z') {
  856.         win_status_clear();
  857.  
  858.         return (TRUE);
  859.     }
  860.  
  861.     /* Keep on reading device names */
  862.  
  863.     count = 0;
  864.  
  865.     while (!done) {
  866.         switch(state) {
  867.             case RDSTATE_NORMAL:
  868.                 /* Get the next byte */
  869.  
  870.                 if (!serial_data_get(&data_byte,1)) {
  871.                     error("Unable to read directories data.",
  872. ERROR_WARNING,__LINE__,__FILE__);
  873.  
  874.                     return (FALSE);
  875.                 }
  876.  
  877.                 /* If it's a normal character */
  878.  
  879.                 if (data_byte != 0x1B)
  880.                     lvdata.fname[count++] = data_byte;
  881.                 else
  882.                     state = RDSTATE_ESCCODE;
  883.  
  884.                 break;
  885.             case RDSTATE_ESCCODE:
  886.                 /* Get the ESC code */
  887.  
  888.                 if (!serial_data_get(&data_byte,1)) {
  889.                     error("Unable to read directories data.",
  890. ERROR_WARNING,__LINE__,__FILE__);
  891.  
  892.                     return (FALSE);
  893.                 }
  894.  
  895.                 /* If end of devices */
  896.  
  897.                 if (data_byte == 'Z') {
  898.                     lvdata.fname[count] ='\0';
  899.  
  900.                     win_listview_add(&lvdata,ZFILETYPE_DIR);
  901.  
  902.                     done = TRUE;
  903.                 }
  904.                 else if (data_byte == 'N') {
  905.                     lvdata.fname[count] ='\0';
  906.  
  907.                     win_listview_add(&lvdata,ZFILETYPE_DIR);
  908.  
  909.                     count = 0;
  910.                 }
  911.                 else {
  912.                     error("Unknown directories data.|"
  913. "ESC code received was not either\n"
  914. "N or Z.",ERROR_WARNING,__LINE__,__FILE__);
  915.  
  916.                     return (FALSE);
  917.                 }
  918.  
  919.                 state = RDSTATE_NORMAL;
  920.  
  921.                 break;
  922.             default:
  923.                 error("Unknown RDSTATE.",ERROR_INTERNAL,
  924. __LINE__,__FILE__);
  925.                 break;
  926.         }
  927.     }
  928.  
  929.     /* Clear the status */
  930.  
  931.     win_status_clear();
  932.  
  933.     /* Return OK */
  934.  
  935.     return (TRUE);
  936. }
  937.  
  938. /*
  939. Function : BOOL serial_filenames()
  940. Purpose : Returns filenames available on prj->zpath device on the Z88.
  941.     Returns TRUE on success, FALSE otherwise.
  942. */
  943.  
  944. BOOL serial_filenames()
  945. {
  946.     WORD tags_filenames[STRLEN_ZPATH];
  947.  
  948.     WORD tag_num = 0;
  949.     WORD count;
  950.  
  951.     UBYTE tags_get[2];
  952.     UBYTE data_byte;
  953.  
  954.     BOOL done = FALSE;
  955.  
  956.     struct listviewdata lvdata;
  957.  
  958.     rdstate_e state = RDSTATE_NORMAL;
  959.  
  960.     /* Synchronise the serial */
  961.  
  962.     win_status_set("Synchronising...");
  963.  
  964.     if (!serial_sync()) {
  965.         win_status_clear();
  966.  
  967.         return(FALSE);
  968.     }
  969.  
  970.     /* Set up request */
  971.  
  972.     tags_filenames[tag_num++] = 0x001B;        /* ESC */
  973.     tags_filenames[tag_num++] = 0x004E;        /* 'N' */
  974.  
  975.     for (count = 0; prj->zpath[count] != '\0'; count++)
  976.         tags_filenames[tag_num++] = (WORD)prj->zpath[count];
  977.  
  978.     tags_filenames[tag_num++] = 0x001B;        /* ESC */
  979.     tags_filenames[tag_num++] = 0x005A;        /* 'Z' */
  980.     tags_filenames[tag_num] = -1;
  981.  
  982.     /* Send the message */
  983.  
  984.     win_status_set("Sending data...");
  985.  
  986.     if (!serial_data_put(tags_filenames,FALSE)) {
  987.         win_status_clear();
  988.  
  989.         return (FALSE);
  990.     }
  991.  
  992.     /* Get reply */
  993.  
  994.     win_status_set("Receiving data...");
  995.  
  996.     /* Get tags, should be ESC N or ESC Z */
  997.  
  998.     if (!serial_data_get(tags_get,2)) {
  999.         error("Unable to get reply from Z88.",ERROR_WARNING,
  1000. __LINE__,__FILE__);
  1001.  
  1002.         win_status_clear();
  1003.  
  1004.         return(FALSE);
  1005.     }
  1006.  
  1007.     if (tags_get[0] != 0x1B) {
  1008.         error("Unknown Z88 reply.|"
  1009. "Expecting ESC N or ESC Z in reply\n"
  1010. "to devices request.",ERROR_WARNING,__LINE__,__FILE__);
  1011.  
  1012.         win_status_clear();
  1013.  
  1014.         return(FALSE);
  1015.     }
  1016.  
  1017.     if ((tags_get[1] != 'N') && (tags_get[1] != 'Z')) {
  1018.         error("Unknown Z88 reply.|"
  1019. "Expecting ESC N or ESC Z in reply\n"
  1020. "to devices request.",ERROR_WARNING,__LINE__,__FILE__);
  1021.  
  1022.         win_status_clear();
  1023.  
  1024.         return(FALSE);
  1025.     }
  1026.  
  1027.     /* If it's the end, no devices were returned */
  1028.  
  1029.     if (tags_get[1] == 'Z') {
  1030.         win_status_clear();
  1031.  
  1032.         return (TRUE);
  1033.     }
  1034.  
  1035.     /* Keep on reading device names */
  1036.  
  1037.     count = 0;
  1038.  
  1039.     while (!done) {
  1040.         switch(state) {
  1041.             case RDSTATE_NORMAL:
  1042.                 /* Get the next byte */
  1043.  
  1044.                 if (!serial_data_get(&data_byte,1)) {
  1045.                     error("Unable to read filenames data.",
  1046. ERROR_WARNING,__LINE__,__FILE__);
  1047.  
  1048.                     return (FALSE);
  1049.                 }
  1050.  
  1051.                 /* If it's a normal character */
  1052.  
  1053.                 if (data_byte != 0x1B)
  1054.                     lvdata.fname[count++] = data_byte;
  1055.                 else
  1056.                     state = RDSTATE_ESCCODE;
  1057.  
  1058.                 break;
  1059.             case RDSTATE_ESCCODE:
  1060.                 /* Get the ESC code */
  1061.  
  1062.                 if (!serial_data_get(&data_byte,1)) {
  1063.                     error("Unable to read filenames data.",
  1064. ERROR_WARNING,__LINE__,__FILE__);
  1065.  
  1066.                     return (FALSE);
  1067.                 }
  1068.  
  1069.                 /* If end of devices */
  1070.  
  1071.                 if (data_byte == 'Z') {
  1072.                     lvdata.fname[count] ='\0';
  1073.  
  1074.                     win_listview_add(&lvdata,ZFILETYPE_FILE);
  1075.  
  1076.                     done = TRUE;
  1077.                 }
  1078.                 else if (data_byte == 'N') {
  1079.                     lvdata.fname[count] ='\0';
  1080.  
  1081.                     win_listview_add(&lvdata,ZFILETYPE_FILE);
  1082.  
  1083.                     count = 0;
  1084.                 }
  1085.                 else {
  1086.                     error("Unknown filenames data.|"
  1087. "ESC code received was not either\n"
  1088. "N or Z.",ERROR_WARNING,__LINE__,__FILE__);
  1089.  
  1090.                     return (FALSE);
  1091.                 }
  1092.  
  1093.                 state = RDSTATE_NORMAL;
  1094.  
  1095.                 break;
  1096.             default:
  1097.                 error("Unknown RDSTATE.",ERROR_INTERNAL,
  1098. __LINE__,__FILE__);
  1099.                 break;
  1100.         }
  1101.     }
  1102.  
  1103.     /* Clear the status */
  1104.  
  1105.     win_status_clear();
  1106.  
  1107.     /* Return OK */
  1108.  
  1109.     return (TRUE);
  1110. }
  1111.  
  1112. /*
  1113. Function : BOOL serial_binary_get(char *zname)
  1114. Purpose : Gets the selected file. The current Z88 path is taken from
  1115.     prj->zpath and the Amiga path from prj->path_binary_get.
  1116.     Returns TRUE on success, FALSE otherwise.
  1117. */
  1118.  
  1119. BOOL serial_binary_get(char *zname)
  1120. {
  1121.     LONG count;
  1122.  
  1123.     WORD tags_get[STRLEN_ZPATH];
  1124.  
  1125.     WORD tag_num = 0;
  1126.     WORD data_word;
  1127.  
  1128.     BOOL done = FALSE;
  1129.  
  1130.     FILE *fh;
  1131.  
  1132.     char fname[STRLEN_FNAME];
  1133.     char zfname[STRLEN_ZPATH];
  1134.     char status_text[STRLEN_STATUS];
  1135.  
  1136.     /* Create the Amiga filename */
  1137.  
  1138.     strcpy(fname,prj->path_binary_get);
  1139.     AddPart(fname,zname,STRLEN_FNAME);
  1140.  
  1141.     /* Create the Z88 filename */
  1142.  
  1143.     strcpy(zfname,prj->zpath);
  1144.     strcat(zfname,zname);
  1145.  
  1146.     /* Synchronise the serial */
  1147.  
  1148.     win_status_set("Synchronising...");
  1149.  
  1150.     if (!serial_sync()) {
  1151.         win_status_clear();
  1152.  
  1153.         return(FALSE);
  1154.     }
  1155.  
  1156.     /* Set up request */
  1157.  
  1158.     tags_get[tag_num++] = 0x001B;        /* ESC */
  1159.     tags_get[tag_num++] = 0x0047;        /* 'G' */
  1160.  
  1161.     for (count = 0; zfname[count] != '\0'; count++)
  1162.         tags_get[tag_num++] = (WORD)zfname[count];
  1163.  
  1164.     tags_get[tag_num++] = 0x001B;        /* ESC */
  1165.     tags_get[tag_num++] = 0x005A;        /* 'Z' */
  1166.     tags_get[tag_num] = -1;
  1167.  
  1168.     /* Send the message */
  1169.  
  1170.     win_status_set("Sending data...");
  1171.  
  1172.     if (!serial_data_put(tags_get,FALSE)) {
  1173.         win_status_clear();
  1174.  
  1175.         return (FALSE);
  1176.     }
  1177.  
  1178.     /* Open the Amiga file */
  1179.  
  1180.     fh = fopen(fname,"wb");
  1181.  
  1182.     if (!fh) {
  1183.         error("Unable to open Amiga file.",ERROR_WARNING,__LINE__,
  1184. __FILE__);
  1185.         win_status_clear();
  1186.  
  1187.         return (FALSE);
  1188.     }
  1189.  
  1190.     /* Set up a small buffer on file */
  1191.  
  1192.     setvbuf(fh,NULL,_IOFBF,1024);
  1193.  
  1194.     /* Receive the file */
  1195.  
  1196.     count = 0;
  1197.  
  1198.     while (!done) {
  1199.         /* Update the status gadget */
  1200.  
  1201.         if (!(count++ & 0x03FF)) {
  1202.             sprintf(status_text,"Getting %s (%dK done)...",zname,
  1203. count / 1024);
  1204.             win_status_set(status_text);
  1205.         }
  1206.  
  1207.         /* Get the next byte */
  1208.  
  1209.         if (!serial_data_get_single(&data_word)) {
  1210.             error("Unable to get data.",ERROR_WARNING,
  1211. __LINE__,__FILE__);
  1212.             fclose(fh);
  1213.  
  1214.             win_status_clear();
  1215.  
  1216.             return (FALSE);
  1217.         }
  1218.  
  1219.         /* If we've finished */
  1220.  
  1221.         if (data_word == -1)
  1222.             done = TRUE;
  1223.         else {
  1224.             /* It's a normal character */
  1225.  
  1226.             if (fputc((int)data_word,fh) == EOF) {
  1227.  
  1228.                 fclose(fh);
  1229.  
  1230.                 win_status_clear();
  1231.  
  1232.                 return (FALSE);
  1233.             }
  1234.         }
  1235.     }
  1236.  
  1237.     /* Clear the status */
  1238.  
  1239.     win_status_clear();
  1240.  
  1241.     /* Close Amiga file */
  1242.  
  1243.     fclose(fh);
  1244.  
  1245.     /* Return OK */
  1246.  
  1247.     return (TRUE);
  1248. }
  1249.  
  1250. /*
  1251. Function : BOOL serial_binary_put(char *file,char *path)
  1252. Purpose : Puts the selected file. The current Z88 path is taken from
  1253.     prj->zpath. Returns TRUE on success, FALSE otherwise.
  1254. */
  1255.  
  1256. BOOL serial_binary_put(char *path,char *file)
  1257. {
  1258.     LONG count;
  1259.  
  1260.     WORD tags_put[STRLEN_ZPATH];
  1261.     WORD tag_num = 0;
  1262.     WORD l;
  1263.  
  1264.     BOOL done = FALSE;
  1265.  
  1266.     FILE *fh;
  1267.  
  1268.     char *chrptr;
  1269.  
  1270.     char fname[STRLEN_FNAME];
  1271.     char zfile[STRLEN_FNAME];
  1272.     char zfname[STRLEN_ZPATH];
  1273.     char status_text[STRLEN_STATUS];
  1274.  
  1275.     int num_periods = 0;
  1276.     int chr;
  1277.  
  1278.     /* Build full Amiga filename */
  1279.  
  1280.     strcpy(fname,path);
  1281.     AddPart(fname,file,STRLEN_FNAME);
  1282.  
  1283.     /* Build Z88 filename */
  1284.  
  1285.     strcpy(zfname,prj->zpath);
  1286.  
  1287.     /* Chop length to max 12 chars */
  1288.  
  1289.     strncpy(zfile,file,12);
  1290.     zfile[11] = '\0';
  1291.  
  1292.     /* Make sure there's at most 1 period */
  1293.  
  1294.     for (l = 0; zfile[l] != '\0'; l++) {
  1295.         if (zfile[l] == '.')
  1296.             num_periods++;
  1297.     }
  1298.  
  1299.     if (num_periods >= 2) {
  1300.         for (l = 0; l < (num_periods - 1); l++) {
  1301.             chrptr = strchr(zfile,'.');
  1302.  
  1303.             *chrptr = 'X';
  1304.         }
  1305.     }
  1306.  
  1307.     /* Remove any non-alphanumeric characters */
  1308.  
  1309.     for (l = 0; l < strlen(zfile); l++) {
  1310.         if ((!isalnum(zfile[l])) && (zfile[l] != '.'))
  1311.             zfile[l] = 'X';
  1312.     }
  1313.  
  1314.     /* Make sure the extension is 3 characters max */
  1315.  
  1316.     chrptr = strchr(zfile,'.');
  1317.  
  1318.     if (chrptr) {
  1319.         if (strlen(chrptr) > 4)
  1320.             chrptr[4] = '\0';
  1321.     }
  1322.  
  1323.     strcat(zfname,zfile);
  1324.  
  1325.     /* Synchronise the serial */
  1326.  
  1327.     win_status_set("Synchronising...");
  1328.  
  1329.     if (!serial_sync()) {
  1330.         win_status_clear();
  1331.  
  1332.         return(FALSE);
  1333.     }
  1334.  
  1335.     /* Set up request */
  1336.  
  1337.     tags_put[tag_num++] = 0x001B;        /* ESC */
  1338.     tags_put[tag_num++] = 0x0053;        /* 'S' */
  1339.     tags_put[tag_num++] = 0x001B;        /* ESC */
  1340.     tags_put[tag_num++] = 0x004E;        /* 'N' */
  1341.  
  1342.     for (count = 0; zfname[count] != '\0'; count++)
  1343.         tags_put[tag_num++] = (WORD)zfname[count];
  1344.  
  1345.     tags_put[tag_num++] = 0x001B;        /* ESC */
  1346.     tags_put[tag_num++] = 0x0046;        /* 'F' */
  1347.     tags_put[tag_num] = -1;
  1348.  
  1349.     /* Send the message */
  1350.  
  1351.     win_status_set("Sending data...");
  1352.  
  1353.     if (!serial_data_put(tags_put,FALSE)) {
  1354.         win_status_clear();
  1355.  
  1356.         return (FALSE);
  1357.     }
  1358.  
  1359.     /* Open the Amiga file */
  1360.  
  1361.     fh = fopen(fname,"rb");
  1362.  
  1363.     if (!fh) {
  1364.         error("Unable to open Amiga file.",ERROR_WARNING,__LINE__,
  1365. __FILE__);
  1366.         win_status_clear();
  1367.  
  1368.         return (FALSE);
  1369.     }
  1370.  
  1371.     /* Set up a small buffer on file */
  1372.  
  1373.     setvbuf(fh,NULL,_IOFBF,1024);
  1374.  
  1375.     /* Receive the file */
  1376.  
  1377.     count = 0;
  1378.  
  1379.     while (!done) {
  1380.         /* Update the status gadget */
  1381.  
  1382.         if (!(count++ & 0x03FF)) {
  1383.             sprintf(status_text,"Putting %s (%dK done)...",zfile,
  1384. count / 1024);
  1385.             win_status_set(status_text);
  1386.         }
  1387.  
  1388.         chr = fgetc(fh);
  1389.  
  1390.         if (chr == EOF)
  1391.             done = TRUE;
  1392.         else {
  1393.             tags_put[0] = (WORD)chr;
  1394.             tags_put[1] = -1;
  1395.  
  1396.             if (!serial_data_put(tags_put,TRUE)) {
  1397.                 error("Unable to put data.",ERROR_WARNING,
  1398. __LINE__,__FILE__);
  1399.  
  1400.                 done = TRUE;
  1401.             }
  1402.         }
  1403.     }
  1404.  
  1405.     tags_put[0] = 0x001B;    /* ESC */
  1406.     tags_put[1] = 0x005A;    /* 'Z' */
  1407.     tags_put[2] = -1;
  1408.  
  1409.     if (!serial_data_put(tags_put,FALSE))
  1410.         error("Unable to put data.",ERROR_WARNING,__LINE__,__FILE__);
  1411.  
  1412.     win_status_clear();
  1413.  
  1414.     /* Close file */
  1415.  
  1416.     fclose(fh);
  1417.  
  1418.     /* Return OK */
  1419.  
  1420.     return (TRUE);
  1421. }
  1422.